package auth

import (
	"strings"

	"goweb/ext/e"
	"goweb/ext/settings"
	"goweb/models/auth"
	"goweb/utils/commons"
	"goweb/utils/redis"

	"github.com/json-iterator/go"
)

var json = jsoniter.ConfigCompatibleWithStandardLibrary

type User struct {
	auth.User
}

type Role struct {
	auth.Role
}

type Per struct {
	auth.Permission
}

type SetPerKey struct {
	Uid   string
	PerId []string
}

func (u *User) Auth(source string) (string, string, string, bool,int, []string) {
	staf, sourceId, uid, uTime,code, flag := auth.Auth(u.UserName, u.Password, source)
	//m := make(map[string]string)
	arr := []string{}
	if staf == 1 {
		perId := GetUserRedisPer(uid)

		for _, v := range perId {
			value, _ := redis.GetValue(v, conf.RDb3)
			arr = append(arr, value[1:len(value)-1])
		}
		return sourceId, uTime, uid, flag, code,arr
	} else {
		return sourceId, uTime, uid, flag, code,nil
	}
}

func (u *User) Check() (string, string, bool) {
	return auth.CheckAuth(u.Uid)
}

func (u *User) AddUser(source string) bool {
	return auth.AddUser(u.UserName, u.Password, source)
}

func (u *User) UpdateUser() bool {

	return auth.UpdateUser(u.Uid, map[string]interface{}{
		"UserName": u.UserName,
		"Password": u.Password,
	})
}

func (u *User) ExistUserByUid() string {
	return auth.ExistUserSourceByUid(u.Uid)
}

func (r *Role) ExistRoleByID() bool {
	return auth.ExistRoleByID(r.RoleId)
}

func (r *Role) AddRole() bool {
	return auth.AddRole(r.RoleId, r.Name)
}

func GetAllSource() []auth.SourceM {
	return auth.GetAllSourceM()
}

func (u *User) GetUserPer() (bool, []map[string]string) {
	if flag, query := auth.GetUserPer(u.Uid); flag {
		s := SetPerKey{}
		for _, v := range query {
			s.Uid = v["Uid"]
			s.PerId = append(s.PerId, v["PerId"])
		}
		marshal, _ := json.Marshal(&s)

		redis.SetValue(conf.PERX_PER+u.Uid, string(marshal), 60*60*24*30*36, conf.RDb0)
		//GetUserRedisPer(uid)
		return true, query
	}

	return false, nil

}

func GetUserRedisPer(uid string) []string {
	value, e := redis.GetValue(conf.PERX_PER+uid, conf.RDb2)
	var s *SetPerKey
	if commons.CheckErr(e) {
		str := strings.Replace(string(value), "\\", "", -1)
		unmarshal := json.Unmarshal([]byte(str[1:len(str)-1]), &s)
		print(unmarshal)
		return s.PerId

	}
	return nil
}

/**
获取所有权限
*/
func (p *Per) GetAllPer() ([]auth.Permission, bool) {
	return auth.GetAllPer()
}

/**
更新权限
*/
func (r *Role) UpdateUserPer(uid, perId, url string) bool {
	if !auth.UpdateUserPer(r.RoleId, r.Name, uid, perId, url) {
		return false
	}

	/**
	修改完权限后获取该用户最新的权限
	*/
	getUserPer, query := auth.GetUserPer(uid)
	s := SetPerKey{}
	if getUserPer {
		for _, v := range query {
			s.Uid = v["uid"]
			s.PerId = append(s.PerId, v["perId"])
		}
		marshal, _ := json.Marshal(&s)
		redis.SetValue(conf.PERX_PER+uid, marshal, 60*60*24*30*36, conf.RDb2)
		//GetUserRedisPer(uid)
		return true
	}

	return false
}

/**
校验权限
*/

func CheckPer(uid, uri string) int {

	if auth.ExistUserSourceByUid(uid) == conf.STRING_FLAG {
		//用户不存在
		return e.USER_NOT_EXIST
	}
	per := GetUserRedisPer(uid)
	bytes, ex := redis.GetValue(uri, conf.RDb0)
	if !commons.CheckErr(ex) {
		return e.GET_ERROR
	}
	if per == nil {
		return e.PER_NOT_EXIST
	} else {
		if commons.BinarySearch(per, string(bytes)) == -1 {
			return e.ERROR_TOKEN
		}
	}
	return e.SUCCESS
}

func InitPer() {
	per, err := auth.InitPer()
	if commons.CheckErr(err) {
		for _, v := range per {
			redis.SetValue(v.Url, v.PerId, 60*60*24*30*36, conf.RDb0)
			redis.SetValue(v.PerId, v.Url, 60*60*24*30*36, conf.RDb3)
		}
	}

}

func GetAllUserPer() {
	per, err := auth.GetAllUserPer()
	if commons.CheckErr(err) {
		m := make(map[string][]string)
		for _, v := range per {
			m[v["Uid"]] = append(m[v["Uid"]], v["PerId"])
		}
		for uid, v := range m {
			s := SetPerKey{}
			s.Uid = uid
			s.PerId = v
			marshal, _ := json.Marshal(&s)
			redis.SetValue(conf.PERX_PER+uid, string(marshal), 60*60*24*30*36, conf.RDb2)
		}

	}
}
